package com.itheima.service.Impl;

import com.itheima.common.pojo.vo.BusinessReportVO;
import com.itheima.common.pojo.vo.MemberVO;
import com.itheima.common.pojo.vo.OrderReportVO;
import com.itheima.common.pojo.vo.SetmealVO;
import com.itheima.mapper.ReportMapper;
import com.itheima.service.ReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private ReportService reportService;

    /**
     * 会员统计
     * @param begin
     * @param end
     * @return
     */
    public MemberVO getMemberReport(LocalDate begin, LocalDate end) {

        List<String> monthList = new ArrayList<>();
        List<Integer> memberCountList = new ArrayList<>();

        // 一次性查询所有月份的注册会员数,查询结果以List<Map<String, Object>>的形式返回，其中每个Map包含月份和对应的会员数量
        List<Map<String, Object>> monthlyData = reportMapper.getMemberCountByMonth(
                LocalDateTime.of(begin, LocalTime.MIN),
                LocalDateTime.of(end, LocalTime.MAX)
        );

        // 生成月份列表
        LocalDate current = begin;
        Map<String, Integer> monthCountMap = new HashMap<>();

        // 将数据库结果转成Map便于查找
        //这段代码的功能是将从数据库查询得到的每月会员统计数据（monthlyData）转换为一个以月份为键、会员数量为值的映射表（monthCountMap）
        for (Map<String, Object> data : monthlyData) {
            String month = data.get("month").toString();
            Integer count = Integer.valueOf(data.get("count").toString());
            monthCountMap.put(month, count);
        }

        // 构建最终结果
        while (!current.isAfter(end)) {
            //使用String.format方法格式化字符串。
            String monthKey = String.format("%d.%02d.%02d",  //%d占位符分别替换为当前日期的年份、月份和该月最后一天的日期。
                    current.getYear(),
                    current.getMonthValue(),
                    current.withDayOfMonth(current.lengthOfMonth()).getDayOfMonth()  //获取当月最后一天
            );
            monthList.add(monthKey);

            // 从Map中获取会员数，如果不存在则为0
            String mapKey = String.format("%d.%02d", current.getYear(), current.getMonthValue());
            //使用getOrDefault方法从monthCountMap中查找键mapKey,如果找到对应键，则返回其值；否则返回默认值0
            Integer count = monthCountMap.getOrDefault(mapKey, 0);
            memberCountList.add(count);

            current = current.plusMonths(1);
        }
        // 封装返回结果
        return MemberVO.builder()
                .months(monthList)
                .memberCount(memberCountList)
                .build();
    }

    /**
     * 获取套餐预约占比统计数据
     * @return
     */
    public SetmealVO getSetmealReport() {
        // 查询套餐预约数据
        List<Map<String, Object>> setmealData = reportMapper.getSetmealReport();
        List<String> setmealNames = new ArrayList<>(); //用于存储套餐名称
        List<SetmealVO.SetmealCount> setmealCounts = new ArrayList<>();  //用于存储套餐预约数量的统计信息

        // 处理统计数据
        // 计算总预约数
        int totalCount = 0;
        for (Map<String, Object> data : setmealData) {
            String name = data.get("name").toString();
            Integer count = Integer.valueOf(data.get("value").toString());
            totalCount += count;

            //计算占比
            String proportion = "0.00%";
            if (totalCount > 0){
                // 计算百分比，保留两位小数
                double percentage = (double) count / totalCount * 100;
                proportion = String.format("%.2f%%", percentage);
            }

            setmealNames.add(name);
            setmealCounts.add(SetmealVO.SetmealCount.builder()
                    .name(name)
                    .value(count)
                    .proportion(proportion)
                    .build());
        }
        // 封装返回结果
        return SetmealVO.builder()
                .setmealNames(setmealNames)
                .setmealCounts(setmealCounts)
                .build();
    }

    /**
     * 预约到诊数据统计
     * @return
     */
    public OrderReportVO getOrderReport() {
        //获取当前日期
        LocalDate end = LocalDate.now();
        //获取12个月前的日期
        LocalDate begin = end.minusMonths(11);

        List<String> monthList = new ArrayList<>();
        List<Integer> orderCountList = new ArrayList<>();
        List<Integer> visitCountList = new ArrayList<>();

        // 查询12个月的预约和到诊数据
        List<Map<String, Object>> orderData = reportMapper.getOrderCountByMonth(
                LocalDateTime.of(begin, LocalTime.MIN),
                LocalDateTime.of(end, LocalTime.MAX)
        );

        // 将数据转换为Map便于查找
        Map<String, Map<String, Integer>> monthDataMap = new HashMap<>();
        if (orderData != null) {
            for (Map<String, Object> data : orderData) {
                if (data != null && data.get("month") != null) {
                    String month = data.get("month").toString();
                    // 使用 0 作为默认值，避免空指针
                    Integer orderCount = data.get("order_count") != null ?
                            Integer.valueOf(data.get("order_count").toString()) : 0;
                    Integer visitCount = data.get("visit_count") != null ?
                            Integer.valueOf(data.get("visit_count").toString()) : 0;

                    Map<String, Integer> countMap = new HashMap<>();
                    countMap.put("orderCount", orderCount);
                    countMap.put("visitCount", visitCount);
                    monthDataMap.put(month, countMap);
                }
            }
        }

        // 生成月份列表和对应的统计数据
        LocalDate current = begin;
        int totalOrderCount = 0;
        int totalVisitCount = 0;

        while (!current.isAfter(end)) {
            // 修改月份格式，确保与数据库返回格式一致
            String monthKey = String.format("%d.%02d.%02d",
                    current.getYear(),
                    current.getMonthValue(),
                    current.withDayOfMonth(current.lengthOfMonth()).getDayOfMonth()
            );
            monthList.add(monthKey);

            // 获取当月数据，注意格式要与数据库返回的格式一致
            String mapKey = String.format("%d.%02d", current.getYear(), current.getMonthValue());
            Map<String, Integer> countMap = monthDataMap.getOrDefault(mapKey, new HashMap<>());

            int orderCount = countMap.getOrDefault("orderCount", 0);
            int visitCount = countMap.getOrDefault("visitCount", 0);

            orderCountList.add(orderCount);
            visitCountList.add(visitCount);

            totalOrderCount += orderCount;
            totalVisitCount += visitCount;
            current = current.plusMonths(1);
        }

        // 封装返回结果
        return OrderReportVO.builder()
                .months(monthList)
                .orderCount(orderCountList)
                .visitCount(visitCountList)
                .build();
    }

    /**
     * 获取运营统计数据
     * @return
     */
    public BusinessReportVO getBusinessReportData() {
        // 获取当前日期
        LocalDate today = LocalDate.now();

        // 获取本周一日期
        LocalDate thisWeekMonday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        // 获取本月第一天
        LocalDate thisMonthFirst = today.with(TemporalAdjusters.firstDayOfMonth());

        // 获取会员统计数据
        Integer todayNewMember = reportMapper.getTodayNewMember(today);
        Integer totalMember = reportMapper.getTotalMember();
        Integer thisWeekNewMember = reportMapper.getThisWeekNewMember(thisWeekMonday);
        Integer thisMonthNewMember = reportMapper.getThisMonthNewMember(thisMonthFirst);

        // 获取预约到诊数据
        Integer todayOrderNumber = reportMapper.getTodayOrderNumber(today);
        Integer todayVisitsNumber = reportMapper.getTodayVisitsNumber(today);
        Integer thisWeekOrderNumber = reportMapper.getThisWeekOrderNumber(thisWeekMonday);
        Integer thisWeekVisitsNumber = reportMapper.getThisWeekVisitsNumber(thisWeekMonday);
        Integer thisMonthOrderNumber = reportMapper.getThisMonthOrderNumber(thisMonthFirst);
        Integer thisMonthVisitsNumber = reportMapper.getThisMonthVisitsNumber(thisMonthFirst);

        // 获取热门套餐数据
        List<Map<String, Object>> hotSetmealData = reportMapper.getHotSetmeal();
        List<BusinessReportVO.HotSetmeal> hotSetmeals = new ArrayList<>();

        if (hotSetmealData != null) {
            for (Map<String, Object> data : hotSetmealData) {
                BusinessReportVO.HotSetmeal hotSetmeal = BusinessReportVO.HotSetmeal.builder()
                        .name(data.get("name").toString())
                        .setmeal_count(Integer.valueOf(data.get("setmeal_count").toString()))
                        .proportion(Double.valueOf(data.get("proportion").toString()))
                        .build();
                hotSetmeals.add(hotSetmeal);
            }
        }

        // 封装返回结果
        return BusinessReportVO.builder()
                .reportDate(today.toString())
                .todayNewMember(todayNewMember)
                .totalMember(totalMember)
                .thisWeekNewMember(thisWeekNewMember)
                .thisMonthNewMember(thisMonthNewMember)
                .todayOrderNumber(todayOrderNumber)
                .todayVisitsNumber(todayVisitsNumber)
                .thisWeekOrderNumber(thisWeekOrderNumber)
                .thisWeekVisitsNumber(thisWeekVisitsNumber)
                .thisMonthOrderNumber(thisMonthOrderNumber)
                .thisMonthVisitsNumber(thisMonthVisitsNumber)
                .hotSetmeal(hotSetmeals)
                .build();
    }

    /**
     * 导出运营数据报表
     * @param response
     */
    public void exportBusinessReport(HttpServletResponse response) {

        //1.查询数据库，获取营业数据 -- 查询最近30天的数据
        LocalDate dateBegin = LocalDate.now().minusDays(30);
        LocalDate dateEnd = LocalDate.now().minusDays(1);

        try {
        //查询概览数据
        BusinessReportVO businessReportVO = reportService.getBusinessReportData();
        // 获取模板文件
        String templatePath = "template/report_template.xlsx";
        InputStream inputStream = this.getClass().getResourceAsStream(templatePath);
        if (inputStream == null) {
                // 尝试使用另一种方式加载
                inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(templatePath);
        }
        if (inputStream == null) {
            throw new RuntimeException("无法找到报表模板文件");
        }

            // 创建工作簿
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            //获取表格文件的Sheet页
            XSSFSheet sheet = workbook.getSheet("sheet1");
            //填充数据 --时间
            sheet.getRow(2).getCell(5).setCellValue(businessReportVO.getReportDate());
            //获取第五行  会员数据
            XSSFRow row = sheet.getRow(4);
            row.getCell(5).setCellValue(businessReportVO.getTodayNewMember());
            row.getCell(7).setCellValue(businessReportVO.getTotalMember());
            //获取第六行
            row = sheet.getRow(5);
            row.getCell(5).setCellValue(businessReportVO.getThisWeekNewMember());
            row.getCell(7).setCellValue(businessReportVO.getThisMonthNewMember());
            //获取第八行  预约到诊数据
            row = sheet.getRow(7);
            row.getCell(5).setCellValue(businessReportVO.getTodayOrderNumber());
            row.getCell(7).setCellValue(businessReportVO.getTodayVisitsNumber());
            //获取第九行
            row = sheet.getRow(8);
            row.getCell(5).setCellValue(businessReportVO.getThisWeekOrderNumber());
            row.getCell(7).setCellValue(businessReportVO.getThisWeekVisitsNumber());
            //获取第十行
            row = sheet.getRow(9);
            row.getCell(5).setCellValue(businessReportVO.getThisMonthOrderNumber());
            row.getCell(7).setCellValue(businessReportVO.getThisMonthVisitsNumber());
            //填充明细数据  热门套餐数据
            for (int i = 0, len = businessReportVO.getHotSetmeal().size(); i < len; i++) {
                BusinessReportVO.HotSetmeal hotSetmeal = businessReportVO.getHotSetmeal().get(i);
                row = sheet.getRow(12 + i);
                row.getCell(4).setCellValue(hotSetmeal.getName());
                row.getCell(5).setCellValue(hotSetmeal.getSetmeal_count());
                row.getCell(6).setCellValue(hotSetmeal.getProportion());
            }
            // 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=report.xlsx");

            // 输出文件
            workbook.write(response.getOutputStream());
            workbook.close();
            inputStream.close();

        }catch (IOException e) {
            log.error("导出运营数据报表失败", e);
            throw new RuntimeException("导出运营数据报表失败",e);
        }

    }


}
